package com.zenithmind.exam.config;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StopWatch;

/**
 * 考试服务性能监控配置
 * 
 * @author ZenithMind
 * @since 2024-07-01
 */
@Slf4j
@Aspect
@Configuration
public class ExamPerformanceConfig {

    @Autowired
    private MeterRegistry meterRegistry;

    /**
     * 监控Service层方法执行时间
     */
    @Around("execution(* com.zenithmind.exam.service..*(..))")
    public Object monitorServiceMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        String timerName = "exam.service.method.duration";
        
        Timer.Sample sample = Timer.start(meterRegistry);
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        try {
            Object result = joinPoint.proceed();
            
            stopWatch.stop();
            sample.stop(Timer.builder(timerName)
                    .tag("class", className)
                    .tag("method", methodName)
                    .tag("status", "success")
                    .register(meterRegistry));
            
            long executionTime = stopWatch.getTotalTimeMillis();
            if (executionTime > 1000) { // 超过1秒的方法记录警告
                log.warn("慢方法执行: {}.{} 耗时: {}ms", className, methodName, executionTime);
            } else if (executionTime > 100) { // 超过100ms的方法记录信息
                log.info("方法执行: {}.{} 耗时: {}ms", className, methodName, executionTime);
            }
            
            return result;
        } catch (Exception e) {
            stopWatch.stop();
            sample.stop(Timer.builder(timerName)
                    .tag("class", className)
                    .tag("method", methodName)
                    .tag("status", "error")
                    .register(meterRegistry));
            
            log.error("方法执行异常: {}.{} 耗时: {}ms, 异常: {}", 
                    className, methodName, stopWatch.getTotalTimeMillis(), e.getMessage());
            throw e;
        }
    }

    /**
     * 监控Controller层方法执行时间
     */
    @Around("execution(* com.zenithmind.exam.controller..*(..))")
    public Object monitorControllerMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        String timerName = "exam.controller.method.duration";
        
        Timer.Sample sample = Timer.start(meterRegistry);
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        try {
            Object result = joinPoint.proceed();
            
            stopWatch.stop();
            sample.stop(Timer.builder(timerName)
                    .tag("class", className)
                    .tag("method", methodName)
                    .tag("status", "success")
                    .register(meterRegistry));
            
            long executionTime = stopWatch.getTotalTimeMillis();
            if (executionTime > 2000) { // 超过2秒的接口记录警告
                log.warn("慢接口: {}.{} 耗时: {}ms", className, methodName, executionTime);
            }
            
            return result;
        } catch (Exception e) {
            stopWatch.stop();
            sample.stop(Timer.builder(timerName)
                    .tag("class", className)
                    .tag("method", methodName)
                    .tag("status", "error")
                    .register(meterRegistry));
            
            log.error("接口执行异常: {}.{} 耗时: {}ms, 异常: {}", 
                    className, methodName, stopWatch.getTotalTimeMillis(), e.getMessage());
            throw e;
        }
    }

    /**
     * 监控数据库查询方法执行时间
     */
    @Around("execution(* com.zenithmind.exam.mapper..*(..))")
    public Object monitorMapperMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        String timerName = "exam.mapper.method.duration";
        
        Timer.Sample sample = Timer.start(meterRegistry);
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        try {
            Object result = joinPoint.proceed();
            
            stopWatch.stop();
            sample.stop(Timer.builder(timerName)
                    .tag("class", className)
                    .tag("method", methodName)
                    .tag("status", "success")
                    .register(meterRegistry));
            
            long executionTime = stopWatch.getTotalTimeMillis();
            if (executionTime > 500) { // 超过500ms的查询记录警告
                log.warn("慢查询: {}.{} 耗时: {}ms", className, methodName, executionTime);
            }
            
            return result;
        } catch (Exception e) {
            stopWatch.stop();
            sample.stop(Timer.builder(timerName)
                    .tag("class", className)
                    .tag("method", methodName)
                    .tag("status", "error")
                    .register(meterRegistry));
            
            log.error("查询异常: {}.{} 耗时: {}ms, 异常: {}", 
                    className, methodName, stopWatch.getTotalTimeMillis(), e.getMessage());
            throw e;
        }
    }
}
